﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using GoblinXNA.Graphics;
using GoblinXNA.Graphics.Geometry;
using GoblinXNA.Physics;
using GoblinXNA.SceneGraph;
using GoblinXNA.Shaders;
using Microsoft.Xna.Framework;

namespace _3DAR
{
    class PrimitiveGeometryCreator
    {
        private Material _material;
        private IShadowMap _shadowMap;
        private Vector3 _startCreatingPoint;
        private BranchNode _node;
        private GameState.AddMode _addMode;

        private GeometryNode _geometryNode = null;
        private TransformNode _transformNode = null;
        private bool _isCreating;
        private int _updateCounter;

        // updates every 7th time 
        public bool ToUpdate
        {
            get
            {   
                if (_updateCounter > 7)
                {
                    _updateCounter = 0;
                    return this._isCreating;
                }
                this._updateCounter++;
                return false;
            }
        }

        public PrimitiveGeometryCreator(IShadowMap shadowMap, BranchNode node)
        {
            this._node = node;
            _shadowMap = shadowMap;
            _material = new Material();
            _material.Diffuse = new Vector4(0.6f, 0.6f, 0.6f, 1);
            _material.Specular = Color.White.ToVector4();
            _material.SpecularPower = 10;
        }

        public GeometryNode Create(GameState.AddMode addMode)
        {
            PrimitiveModel primitiveModel;
            if (addMode == GameState.AddMode.Box)
                primitiveModel = new TexturedBox(10.0f);
            else
            {
                primitiveModel = new TexturedSphere(5.0f, 10, 10);
            }
            primitiveModel.ShadowAttribute = ShadowAttribute.ReceiveCast;
            primitiveModel.Shader = new SimpleShadowShader(_shadowMap);
            GeometryNode geometryNode = new GeometryNode();
            geometryNode.Model = primitiveModel;
            geometryNode.Material = _material;
            return geometryNode;
        }

        public GeometryNode Create(PrimitiveModel primitiveModel)
        {
            primitiveModel.ShadowAttribute = ShadowAttribute.ReceiveCast;
            primitiveModel.Shader = new SimpleShadowShader(_shadowMap);
            GeometryNode geometryNode = new GeometryNode();
            geometryNode.Model = primitiveModel;
            geometryNode.Material = _material;
            return geometryNode;
        }

        public GeometryNode Create(PrimitiveModel primitiveModel, Color color)
        {
            Material material = new Material();
            material.Diffuse = color.ToVector4();
            material.Specular = Color.White.ToVector4();
            material.SpecularPower = 10;
            return Create(primitiveModel, material);
        }

        public GeometryNode Create(PrimitiveModel primitiveModel, Material material)
        {
            primitiveModel.ShadowAttribute = ShadowAttribute.ReceiveCast;
            primitiveModel.Shader = new SimpleShadowShader(_shadowMap);
            GeometryNode geometryNode = new GeometryNode();
            geometryNode.Model = primitiveModel;
            geometryNode.Material = material;
            return geometryNode;
        }

        public void StartCreating(Vector3 position, GameState.AddMode addMode)
        {
            this._isCreating = true;
            this._startCreatingPoint = position;
            this._addMode = addMode;
            this._geometryNode = new GeometryNode();
            
            GeometryNode geometryNode = new GeometryNode();
            //geometryNode.Material = _material;
            //materialy i tak dalej??
            this._transformNode = new TransformNode();
            this._node.AddChild(_transformNode);
            _transformNode.AddChild(_geometryNode);
            //GoblinXNA.Helpers.Log.Write(position.ToString());
        }

        private void Update(Vector3 endPosition)
        {

            switch (_addMode)
            {
                case GameState.AddMode.Box:
                    float xDim = Math.Abs(_startCreatingPoint.X - endPosition.X);
                    float yDim = Math.Abs(_startCreatingPoint.Y - endPosition.Y);
                    float zDim = Math.Abs(_startCreatingPoint.Z - endPosition.Z);
                    Vector3 position = (this._startCreatingPoint + endPosition) / 2;
                    Vector3 dim =new Vector3(xDim, yDim, zDim);
                    _geometryNode.Model = new TexturedBox(dim) { ShadowAttribute = ShadowAttribute.ReceiveCast, Shader = new SimpleShadowShader(_shadowMap) };
                    _geometryNode.Material = _material;
                    _geometryNode.UserData = dim;
                    _transformNode.Translation = position;
                    break;
                case GameState.AddMode.Sphere:
                    float radius = Vector3.Distance(this._startCreatingPoint, endPosition);
                    if (radius == 0.0f)
                        break;
                    _geometryNode.Model = new TexturedSphere(radius, 50, 50) { ShadowAttribute = ShadowAttribute.ReceiveCast, Shader = new SimpleShadowShader(_shadowMap) };
                    _geometryNode.Material = _material;
                    //todo: save radius as user data
                    _transformNode.Translation = this._startCreatingPoint;
                    break;
            }
            if (_geometryNode != null && _transformNode != null)
            {

            }
        }

        public void UpdateCreating(Vector3 endPosition)
        {
            Update(endPosition);
        }

        public void StopCreating(Vector3 endPosition)
        {
            this._isCreating = false;
            Update(endPosition);
            this._geometryNode = null;
            this._transformNode = null;
        }
    }
}
